package AlexDB.Resolver;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
// import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import AlexDB.Command.CommandTypeAttribute;
import AlexDB.Command.IDbCommandType;

public class Resolve {
    // private InputStream _input;
    // private OutputStream _output;
    private IDbCommandType[] _commandTypes;

    protected Resolve(IDbCommandType[] commandTypes) 
    {
        // _input = input;
        // _output = output;
        _commandTypes = commandTypes;
    }
    
    public static Resolve build(IDbCommandType... commandTypes)
    {
        return new Resolve(commandTypes);
    }

    // public IDbCommandType resolveCommand(String command) throws Exception
    // {
    //     var args = command.split(" ");
    //     var invokeCommand = Arrays.asList(_commandTypes).stream().filter(
    //         item -> item.getClass().getAnnotation(CommandTypeAttribute.class).value() == args[0])
    //     .collect(Collectors.toList());

    //     if(invokeCommand.size() > 1)
    //         throw new Exception("service resolve error: command route repetition.");
    //     if(invokeCommand.size() <= 0)
    //         throw new Exception("service resolve command error: not find command type.");
    //     // else if(invokeCommand != null && invokeCommand.size() > 0)
    //     // {
    //     //     invokeCommand.get(0).commandExecute(args);
    //     // }
        
    //     return invokeCommand.get(0);
    // }

    // public IDbCommandType resolveCommand(InputStream input) throws Exception
    // {
    //     StringBuffer out = new StringBuffer();
    //     byte[] b = new byte[4096];
    //     for (int n; (n = input.read(b)) != -1;) {
    //       out.append(new String(b, 0, n));
    //     }

    //     var args = out.toString().split(" ");
    //     var invokeCommand = Arrays.asList(_commandTypes).stream().filter(
    //         item -> item.getClass().getAnnotation(CommandTypeAttribute.class).value() == args[0])
    //     .collect(Collectors.toList());

    //     if(invokeCommand.size() > 1)
    //         throw new Exception("service resolve error: command route repetition.");
    //     if(invokeCommand.size() <= 0)
    //         throw new Exception("service resolve command error: not find command type.");
    //     else if(invokeCommand != null && invokeCommand.size() > 0)
    //     {
    //         invokeCommand.get(0).commandExecute(args);
    //     }
        
    //     return invokeCommand.get(0);
    // }

    public Object[] resolveArgs(String command)
    {
        return command.split(" ");
    }

    public Object[] resolveArgs(InputStream input) throws Exception
    {
        StringBuffer out = new StringBuffer();
        byte[] b = new byte[4096];
        for (int n; (n = input.read(b)) != -1;) {
          out.append(new String(b, 0, n));
        }
        return out.toString().split(" ");
    }

    public IDbCommandType resolveCommand(Object[] args) throws Exception
    {
        var invokeCommand = Arrays.asList(_commandTypes).stream().filter(
            item -> item.getClass().getAnnotation(CommandTypeAttribute.class).value().equals(args[0]))
        .collect(Collectors.toList());

        if(invokeCommand == null || invokeCommand.size() > 1)
            throw new Exception("service resolve error: command route repetition.");
        if(invokeCommand.size() <= 0)
            throw new Exception("service resolve command error: not find command type.");
        return invokeCommand.get(0);
    }

    public static String deresolveResultToString(Object result) throws Exception
    {
        if(result instanceof Object[])
        {
            var strings = "";
            var arrayResult = (Object[])result;
            for (Object object : arrayResult) {
                strings += object + " ";
            }
            return strings;
        }

        if(result instanceof List<?>)
        {
            var listResult = (List<?>)result;
            var strings = "";
            for (Object object : listResult) {
                strings += object.toString() + " ";
            }
            return strings;
        }

        if(result instanceof Object)
        {
            return result.toString();
        }

        throw new Exception("result error.");
    }

    public static void deresolveResultToOutputStream(OutputStream output,Object result)
    {
        try (ObjectOutputStream os = new ObjectOutputStream(output)) {
            os.writeObject(result);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

}

